/*
 * @Author: dingyuwen ding_yuwen@163.com
 * @Date: 2023-01-09 17:18:10
 * @LastEditTime: 2023-11-02 09:55:11
 * @LastEditors: DingYuwen 43669762+DingYuwen@users.noreply.github.com
 * @Description:
 */
import { createStandaloneToast } from '@chakra-ui/toast';
import type { PayloadAction } from '@reduxjs/toolkit';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { $authToken, ImageDTO } from '@tourfly/api';

import userService, { LoginInfo } from '@/api/user.service';
import { setToken } from '@/common/utils';

import { downloadZipImages } from '@/common/utils/downloadImage';
const { toast } = createStandaloneToast();
interface UserInfo {
  username: string;
  [k: string]: any;
}
export interface LoraItem {
  name: string;
  type: number;
  triggerWords: null | undefined | string;
  path: string;
  status: number;
  imgDtoList: { id: string; imgPath: string; [k: string]: any }[];
  [k: string]: any;
}
export interface UserImage {
  id: string;
  imgPath: string;
  thumbnail: string;
  isCollect: number;
  isDeleted?: number;
  metadata?: any;
  [k: string]: any;
}
interface UserState {
  token?: string;
  loading: boolean;
  isLogin: boolean;
  userInfo: UserInfo;
  collectionCategory: any[];
  collectionTag: any[];
  imageFilterClassId: string;
  imageFilterTagIds: string[];
  imageFilterIsCollect: string;
  userResultImage: UserImage[];
  favoriteImage: UserImage[];
  userImageInfoMap: {
    [key: string]: any;
  };
  imageIsFavoriteList: string[];
  userLoraList: LoraItem[];
  downloadImages: boolean;
  downloadImagesList: Array<{ image_url: string; image_name: string }>;
}

const initialState: UserState = {
  loading: false,
  userInfo: {
    username: '',
  },
  isLogin: false,
  collectionCategory: [],
  collectionTag: [],
  imageFilterClassId: '',
  imageFilterTagIds: [],
  imageFilterIsCollect: '',
  userResultImage: [],
  userImageInfoMap: {},
  imageIsFavoriteList: [],
  userLoraList: [],
  favoriteImage: [],
  downloadImages: false,
  downloadImagesList: [],
};

export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    setUserInfo: (state, { payload }) => {
      if (payload.username) {
        state.userInfo = { ...state.userInfo, ...payload };
      }
    },
    setIsLogin: (state, action: PayloadAction<boolean>) => {
      state.isLogin = action.payload;
    },
    setLoading: (state, action: PayloadAction<boolean>) => {
      state.loading = action.payload;
    },
    setUserToken: (state, action: PayloadAction<string>) => {
      state.token = action.payload;
    },
    logout: (state) => {
      state.isLogin = false;
      state.userInfo = {
        username: '',
      };
      state.token = '';
    },
    setCollectionCategory: (state, action: PayloadAction<any[]>) => {
      state.collectionCategory = action.payload;
    },
    setCollectionTag: (state, action: PayloadAction<any[]>) => {
      state.collectionTag = action.payload;
    },
    setImageFilterClassId: (state, action: PayloadAction<string>) => {
      state.imageFilterClassId = action.payload;
    },
    setImageFilterTagId: (state, action: PayloadAction<string[]>) => {
      state.imageFilterTagIds = action.payload;
    },
    setImageFilterIsCollect: (state, action: PayloadAction<string>) => {
      state.userResultImage = [];
      if (!action.payload) {
        state.imageFilterTagIds = [];
        state.imageFilterClassId = '';
      }
      state.imageFilterIsCollect = action.payload;
    },
    setClearImageFilter: (state) => {
      state.imageFilterClassId = '';
      state.imageFilterTagIds = [];
      state.imageFilterIsCollect = '';
    },
    setUserResultImage: (state, action: PayloadAction<UserImage[]>) => {
      const images = action.payload || [];
      images.length &&
        images.forEach((i) => {
          const name = i.imgPath.split('outputs/')[1];
          i.thumbnail = `outputs/thumbnails/${name}`.replace('.png', '.webp');
        });
      const tempImages = state.userResultImage;
      const newImages = images.filter(
        (newImage) =>
          !tempImages.find(
            (i) => i.imgPath === newImage.imgPath && i.id === newImage.id
          )
      );
      if (newImages.length) {
        const newFavorite: string[] = [];
        newImages.forEach((i) => {
          i.isCollect && newFavorite.push(i.id);
        });

        state.userResultImage = tempImages.concat(newImages);
        state.imageIsFavoriteList =
          state.imageIsFavoriteList.concat(newFavorite);
      }
    },
    setUserResultImageFilter: (state, action: PayloadAction<UserImage[]>) => {
      const images = action.payload || [];
      images.length &&
        images.forEach((i) => {
          const name = i.imgPath.split('outputs/')[1];
          i.thumbnail = `outputs/thumbnails/${name}`.replace('.png', '.webp');
        });
      state.userResultImage = images;
      if (images.length) {
        const newFavorite: string[] = [];
        images.forEach((i) => {
          i.isCollect && newFavorite.push(i.id);
        });
        state.imageIsFavoriteList =
          state.imageIsFavoriteList.concat(newFavorite);
      }
    },
    setUserResultImageAfterErrorFilter: (
      state,
      action: PayloadAction<UserImage[]>
    ) => {
      state.userResultImage = action.payload;
    },
    setUserImageInfoMap: (
      state,
      action: PayloadAction<{ key: string; value: any }>
    ) => {
      const { key, value } = action.payload;
      state.userImageInfoMap[key] = value;
    },
    setImageIsFavorite: (
      state,
      action: PayloadAction<{ id: string; isF: boolean }>
    ) => {
      const { id, isF } = action.payload;

      const list = state.imageIsFavoriteList.filter((i) => i !== id);
      isF && list.push(id);
      state.imageIsFavoriteList = list;

      if (!isF) {
        // 取消收藏，从图片列表中移除
        const index = state.favoriteImage.findIndex((i) => i.id === id);
        state.favoriteImage.splice(index, 1);
      } else {
        const image = state.userResultImage.find((i) => i.id === id);
        const newList = state.favoriteImage.filter((i) => i.id !== id);
        if (image) {
          image.isCollect = 1;
          image && newList.unshift(image);
        }
        state.favoriteImage = newList;
      }
    },
    setLoraList: (state, action: PayloadAction<LoraItem[]>) => {
      state.userLoraList = action.payload;
    },
    setFavoriteImage: (state, action: PayloadAction<UserImage[]>) => {
      const images = action.payload || [];
      images.length &&
        images.forEach((i) => {
          const name = i.imgPath.split('outputs/')[1];
          i.thumbnail = `outputs/thumbnails/${name}`.replace('.png', '.webp');
        });
      const tempImages = state.favoriteImage;
      const newImages = images.filter(
        (newImage) =>
          !tempImages.find(
            (i) => i.imgPath === newImage.imgPath && i.id === newImage.id
          )
      );
      if (newImages.length) {
        state.favoriteImage = tempImages.concat(newImages);
      }
    },
    setFavoriteImageFilter: (state, action: PayloadAction<UserImage[]>) => {
      const images = action.payload || [];
      images.length &&
        images.forEach((i) => {
          const name = i.imgPath.split('outputs/')[1];
          i.thumbnail = `outputs/thumbnails/${name}`.replace('.png', '.webp');
        });
      state.favoriteImage = images;
    },
    setDownloadImages: (state) => {
      state.downloadImages = !state.downloadImages;
      state.downloadImagesList = [];
    },
    setDownloadImagesList: (
      state,
      action: PayloadAction<{ selected: boolean; imageDTO: ImageDTO }>
    ) => {
      const { selected, imageDTO } = action.payload;
      const { image_url, image_name } = imageDTO;
      const urlList = state.downloadImagesList.filter(
        (i) => i.image_url !== image_url
      );
      if (selected) {
        urlList.push({ image_url, image_name });
        state.downloadImagesList = urlList;
      } else {
        state.downloadImagesList = urlList;
      }
    },
    handDownloadImages: (state) => {
      downloadZipImages(state.downloadImagesList);
      toast({
        position: 'top',
        description: '已开始下载',
        status: 'success',
        duration: 2000,
        isClosable: true,
      });
      state.downloadImages = false;
      state.downloadImagesList = [];
    },
  },
});

export const {
  setDownloadImages,
  setDownloadImagesList,
  handDownloadImages,
  setUserInfo,
  setUserToken,
  setIsLogin,
  setLoading,
  logout,
  setCollectionTag,
  setCollectionCategory,
  setImageFilterClassId,
  setImageFilterTagId,
  setImageFilterIsCollect,
  setClearImageFilter,
  setUserResultImage,
  setUserResultImageFilter,
  setUserResultImageAfterErrorFilter,
  setUserImageInfoMap,
  setImageIsFavorite,
  setLoraList,
  setFavoriteImage,
  setFavoriteImageFilter,
} = userSlice.actions;

export const loginAction = createAsyncThunk(
  'user/login',
  (loginInfo: LoginInfo, thunkApi) => {
    thunkApi.dispatch(setLoading(true));

    return userService
      .login(loginInfo)
      .then(({ rt, code }) => {
        console.log(code);
        if (Number(code) === 200) {
          const username = loginInfo.username;
          const { userInfo, token } = rt;
          setToken(token);
          $authToken.set(token);
          thunkApi.dispatch(setUserToken(token));
          thunkApi.dispatch(setUserInfo({ ...userInfo, ...{ username } }));
          thunkApi.dispatch(setIsLogin(true));
        }
      })
      .catch((error) => {
        console.log(error.message);
      })
      .finally(() => {
        thunkApi.dispatch(setLoading(false));
      });
  }
);

export default userSlice.reducer;
